import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 文件工具类
 * 
 * @author dongbowen
 *
 */
public class FileUtils {

    /**
     * 拼接路径 concatPath("/mnt/sdcard", "/DCIM/Camera") => /mnt/sdcard/DCIM/Camera
     * concatPath("/mnt/sdcard", "DCIM/Camera") => /mnt/sdcard/DCIM/Camera
     * concatPath("/mnt/sdcard/", "/DCIM/Camera") => /mnt/sdcard/DCIM/Camera
     */
    public static String concatPath(String... paths) {
        StringBuilder result = new StringBuilder();
        if (paths != null) {
            for (String path : paths) {
                if (path != null && path.length() > 0) {
                    int len = result.length();
                    boolean suffixSeparator = len > 0 && result.charAt(len - 1) == File.separatorChar;// 后缀是否是'/'
                    boolean prefixSeparator = path.charAt(0) == File.separatorChar;// 前缀是否是'/'
                    if (suffixSeparator && prefixSeparator) {
                        result.append(path.substring(1));
                    } else if (!suffixSeparator && !prefixSeparator) {// 补前缀
                        result.append(File.separatorChar);
                        result.append(path);
                    } else {
                        result.append(path);
                    }
                }
            }
        }
        return result.toString();
    }

    public static long getFileSize(String fn) {
        File f = null;
        long size = 0;

        try {
            f = new File(fn);
            size = f.length();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            f = null;
        }
        return size < 0 ? null : size;
    }

    public static long getFileSize(File fn) {
        return fn == null ? 0 : fn.length();
    }

    public static String getFileType(String fn, String defaultType) {
        FileNameMap fNameMap = URLConnection.getFileNameMap();
        String type = fNameMap.getContentTypeFor(fn);
        return type == null ? defaultType : type;
    }

    public static String getFileType(String fn) {
        return getFileType(fn, "application/octet-stream");
    }

    public static String getFileExtension(String filename) {
        String extension = "";
        if (filename != null) {
            int dotPos = filename.lastIndexOf(".");
            if (dotPos >= 0 && dotPos < filename.length() - 1) {
                extension = filename.substring(dotPos + 1);
            }
        }
        return extension.toLowerCase(Locale.getDefault());
    }

    public static boolean fileIsExists(String str) {
        try {
            File f = new File(str);
            if (!f.exists()) {
                return false;
            }

        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static boolean deleteFile(File f) {
        if (f != null && f.exists() && !f.isDirectory()) {
            return f.delete();
        }
        return false;
    }

    public static void deleteOtherFiles(File dir, String reservedPrefix) {
        File[] subFiles = dir.listFiles();

        if (subFiles == null) {
            return;
        }

        for (File file : subFiles) {
            if (file.isFile() && !file.getName().startsWith(reservedPrefix)) {
                file.delete();
            }
        }
    }

    public static void deleteDir(File f) {
        if (f != null && f.exists() && f.isDirectory()) {
            for (File file : f.listFiles()) {
                if (file != null) {
                    if (file.isDirectory())
                        deleteDir(file);
                    file.delete();
                }
            }
            f.delete();
        }
    }

    public static void deleteDir(String f) {
        if (f != null && f.length() > 0) {
            deleteDir(new File(f));
        }
    }

    public static boolean deleteFile(String f) {
        if (f != null && f.length() > 0) {
            return deleteFile(new File(f));
        }
        return false;
    }

    /**
     * read file
     * 
     * @param filePath
     * @param charsetName
     *            The name of a supported {@link java.nio.charset.Charset
     *            </code>charset<code>}
     * @return if file not exist, return null, else return content of file
     * @throws RuntimeException
     *             if an error occurs while operator BufferedReader
     */
    public static String readFile(File file, String charsetName) {
        if (file == null || !file.isFile()) {
            return null;
        }

        InputStream input = null;
        try {
            input = new FileInputStream(file);
            byte[] data = new byte[input.available()];
            int readNum = input.read(data);
            return new String(data, 0, readNum, charsetName);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    public static String readFile(String filePath, String charsetName) {
        return readFile(new File(filePath), charsetName);
    }

    public static String readFile(File file) {
        return readFile(file, "utf-8");
    }

    public static boolean writeFile(File file, String text) {
        return writeFile(file, text, Charset.defaultCharset().name());
    }

    public static boolean writeFile(File file, String text, String charsetName) {
        FileOutputStream fos = null;
        boolean ret = false;

        try {
            fos = new FileOutputStream(file);
            fos.write(text.getBytes(charsetName));
            ret = true;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    ret = false;
                    e.printStackTrace();
                }
            }
        }

        return ret;
    }

    /**
     * 文件移动
     * 
     * @param from
     * @param to
     * @return
     */
    public static boolean moveFile(String srcFile, String destPath) {
        // File (or directory) to be moved
        File file = new File(srcFile);

        // Destination directory
        File dir = new File(destPath);

        // Move file to new directory
        boolean success = file.renameTo(new File(dir, file.getName()));

        return success;
    }

    public static boolean stream2file(InputStream input, File output) {
        boolean result = false;

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(output);
            streamCopy(input, fos);
            result = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return result;
    }

    public static boolean copyFile(File from, File to) {
        boolean result = false;

        if (to.equals(from))
            return false;

        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(from);
            fos = new FileOutputStream(to);

            streamCopy(fis, fos);
            result = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return result;
    }

    public static void streamCopy(InputStream input, OutputStream output) throws IOException {
        int size = 10 * 1024;

        byte[] buffer = new byte[size];
        int bytesRead = -1;
        while ((bytesRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
        output.flush();
    }
    
    public static void copyDir(File srcDir, File dstDir) {
        if(!srcDir.isDirectory()) {
            System.err.println(String.format(Locale.getDefault(), 
                    "Src file(%s) isn't directory", srcDir.getAbsolutePath()));
            return;
        }
        
        if(dstDir.exists() && !dstDir.isDirectory()) {
            System.err.println(String.format(Locale.getDefault(), 
                    "Dst file(%s) isn't directory", dstDir.getAbsolutePath()));
            return;
        }
        
        dstDir.mkdirs();
        File[] srcFiles = srcDir.listFiles();
        if(srcFiles == null) {
            return;
        }
        for(File srcFile : srcFiles) {
            if(srcFile.isDirectory()) {
                copyDir(srcFile, new File(dstDir, srcFile.getName()));
            } else {
                copyFile(srcFile, new File(dstDir, srcFile.getName()));
            }
        }
    }

    // public static long readSDCard() {
    // String state = Environment.getExternalStorageState();
    // if (Environment.MEDIA_MOUNTED.equals(state)) {
    // File sdcardDir = Environment.getExternalStorageDirectory();
    // StatFs sf = new StatFs(sdcardDir.getPath());
    // long blockSize = sf.getBlockSize();
    // long blockCount = sf.getBlockCount();
    // long availCount = sf.getAvailableBlocks();
    // Logger.error("", "block大小:" + blockSize + ",block数目:" + blockCount
    // + ",总大小:" + blockSize * blockCount / 1024 + "KB");
    // Logger.error("", "可用的block数目：:" + availCount + ",剩余空间:"
    // + availCount * blockSize / 1024 / 1024 + "mB");
    // return blockSize * blockCount / 1024 / 1024;
    // }
    // return 100;
    // }

    public static boolean isFileExist(String filaName) {
        if (filaName == null || filaName.isEmpty())
            return false;
        try {
            File f = new File(filaName);
            if (!f.exists()) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 读取指定文件夹目录下的所有文件
     * 
     * @param filePath
     * @return
     */
    public static List<File> getFile(File fileDir, FileFilter fileFilter) {
        List<File> fileList = new ArrayList<File>();
        File[] fileArray = fileDir.listFiles(fileFilter);
        if (fileArray == null) {
            return fileList;
        }

        for (File file : fileArray) {
            if (file.isFile()) {
                fileList.add(file);
            } else if (file.isDirectory()) {
                fileList.addAll(getFile(file, fileFilter));
            }
        }
        return fileList;
    }

    public static List<File> getFile(File fileDir) {
        return getFile(fileDir, null);
    }

    public static void createFile(String contentsPath, String filePath) {
        File contents = new File(contentsPath);
        File file = new File(filePath);
        if (!contents.exists()) {// 目录存在返回false
            contents.mkdirs();// 创建一个目录
        }
        if (!file.exists()) {// 文件存在返回false
            try {
                file.createNewFile();// 创建文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
